package com.cashmama.market.api.domain.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cashmama.market.api.domain.enums.SmsReportRankEnum;
import com.cashmama.market.api.domain.enums.UserAccountEnum;
import com.cashmama.market.api.domain.enums.UserToolsEnum;
import com.cashmama.market.api.domain.handler.ConfigHandler;
import com.cashmama.market.api.domain.handler.order.OrdersHandler;
import com.cashmama.market.api.domain.oss.RetryOSSService;
import com.cashmama.market.api.domain.utils.AppUtils;
import com.cashmama.market.api.domain.utils.SmsReportUtils;
import com.cashmama.market.api.domain.vo.RequestLocalInfo;
import com.cashmama.market.api.domain.vo.order.SmsReportInfo;
import com.cashmama.market.api.domain.vo.user.*;
import com.cashmama.market.api.domain.vo.user.profile.*;
import com.cashmama.market.api.infras.app.RequestBasicInfo;
import com.cashmama.market.api.infras.config.ApolloConfigUtil;
import com.cashmama.market.api.infras.consts.RedisKeyConsts;
import com.cashmama.market.api.infras.consts.TimeConsts;
import com.cashmama.market.api.infras.enums.BasicErrorCodeEnum;
import com.cashmama.market.api.infras.enums.JumpRouterEnum;
import com.cashmama.market.api.infras.enums.PackageNameEnum;
import com.cashmama.market.api.infras.enums.ProductCategoryEnum;
import com.cashmama.market.api.infras.enums.error.UserProfileErrorCodeEnum;
import com.cashmama.market.api.infras.enums.error.VerifyCodeErrorCodeEnum;
import com.cashmama.market.api.infras.enums.message.VerifyCodeTypeEnum;
import com.cashmama.market.api.infras.enums.user.LoginTypeEnum;
import com.cashmama.market.api.infras.enums.user.OsTypeEnum;
import com.cashmama.market.api.infras.exception.ApplicationException;
import com.cashmama.market.api.infras.utils.*;
import com.fqgj.base.services.amazon.AmazonS3Service;
import com.fqgj.base.services.oss.OSSService;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.TimeUtils;
import com.fqgj.exception.common.ApiErrorException;
import com.fqgj.xjd.user.client.*;
import com.fqgj.xjd.user.client.enums.*;
import com.fqgj.xjd.user.client.request.*;
import com.fqgj.xjd.user.client.response.*;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.jsoniter.output.JsonStream;
import com.qianli.cashmama.product.facade.ProductFacade;
import com.qianli.cashmama.product.facade.result.AppVo;
import com.qianli.cashmama.product.facade.result.ProductCategory;
import com.qianli.cashmama.trade.client.bill.BillQueryService;
import com.qianli.cashmama.trade.client.trade.TradeQueryService;
import com.qianli.cashmama.trade.client.trade.request.QueryTradeRORequest;
import com.qianli.cashmama.trade.client.trade.response.UserTradeROListResponse;
import com.qianli.cashmama.trade.client.vo.BillVO;
import com.qianli.cashmama.trade.client.vo.TradeVO;
import com.qianli.cashmama.trade.common.enums.BillPaidStatusEnum;
import com.qianli.common.enums.BusinessTypeENUM;
import com.qianli.user.enums.UserAuthEnum;
import com.qianli.user.enums.UserAuthStatusEnum;
import com.qianli.user.facade.auth.UserAuthServiceFacade;
import com.qianli.user.ro.auth.*;
import com.qianli.user.ro.query.UserBaseQueryRO;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: market-api
 * @description
 * @author: frank
 * @create: 2019-12-23 10:54
 **/
@Service
public class ApiUserService {
    private final static Logger LOGGER = LoggerFactory.getLogger(ApiUserService.class);

    @Autowired
    private RedisClient redisClient;
    @Autowired
    private AppUtils appUtils;
    @Autowired
    private ApolloConfigUtil apolloConfigUtil;
    @Autowired
    private ApiUserCenterService apiUserCenterService;
    @Autowired
    private UserService userService;
    @Autowired
    private UserBehaviorService userBehaviorService;
    @Autowired
    private ProductFacade productFacade;
    @Autowired
    UserKycDocumentService userKycDocumentService;
    @Autowired
    private UserEmailService userEmailService;
    @Autowired
    private UserBankService userBankService;
    @Autowired
    private OSSService ossService;
    @Autowired
    private RetryOSSService retryOSSService;
    @Autowired
    private UserDeviceService userDeviceService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserAuthSmsService userAuthSmsService;
    @Autowired
    private ConfigHandler configHandler;
    @Autowired
    private UserAuthServiceFacade userAuthServiceFacade;
    @Autowired
    private IFSCServiceProvider ifscServiceProvider;
    @Autowired
    private UserLevelService userLevelService;
    @Autowired
    private UserActivityService userActivityService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private UserContactService userContactService;
    @Autowired
    private UserPanService userPanService;
    @Autowired
    private BillQueryService billQueryService;
    @Autowired
    private TradeQueryService tradeQueryService;
    @Autowired
    private OrdersHandler ordersHandler;
    @Autowired
    private AmazonS3Service amazonS3Service;
    @Autowired
    private UserEventTrackService userEventTrackService;

    public UserRegisterVO verifyCodeLogin(UserAccess userAccess, String verifycode, String ip) {
        String redisVerifyCodeKey = RedisKeyConsts.VERIFY_CODE_REDIS_KEY_PREFIX + VerifyCodeTypeEnum.VERIFY_TYPE_LOGIN.getName() + userAccess.getMobile().getMobile();
        String redisVerifyCode = redisClient.get(redisVerifyCodeKey);
        if (!userAccess.getMobile().getMobile().equalsIgnoreCase("8050843255")) {
            if (!verifycode.equals(redisVerifyCode)) {
                throw new ApiErrorException(VerifyCodeErrorCodeEnum.VERIFYCODE_NOT_CORRECT);
            }
        }
        String appCode = RequestLocalInfo.getRequestBasicInfo().getAppCode();
        userAppInfoInjection(userAccess, RequestLocalInfo.getRequestBasicInfo(), ip);
        Response<User> userResponse = userService.getUserByMobile(userAccess.getMobile().getMobile());
        if (!userResponse.isSuccess()) {
            throw new ApplicationException(userResponse.getCode(), userResponse.getMsg());
        }

        User user = userResponse.getData();
        boolean newRegister = false;
        //未注册过
        String from = RequestLocalInfo.getRequestBasicInfo().getFrom();
        if (null == user) {
            //PC端 不自动注册
            if (Objects.equals(from, OsTypeEnum.WAP.getDesc())) {
                throw new ApplicationException(UserProfileErrorCodeEnum.USER_PROFILE_NO_EXIST);
            }
            userAccess.setUserProductCategoryList(null);
            Response<UserAccessInfo> response = userService.userRegister(userAccess, appCode);
            if (!response.isSuccess()) {
                throw new ApplicationException(response.getCode(), response.getMsg());
            }
            UserAccessInfo userAuthAccessInfo = response.getData();
            userAccess.setUserCode(userAuthAccessInfo.getUserCode());
            newRegister = true;
        } else {
            userAccess.setUserCode(user.getUserCode());
        }

        if (null != userAccess.getUserAppInfo() && StringUtils.isNotEmpty(userAccess.getUserAppInfo().getClientId())) {
            //更新用户的 设备 id
            userBehaviorService.updateOrAddUserClientIdByUserCode(userAccess.getUserCode(), userAccess.getUserAppInfo().getClientId());
        }
        redisClient.del(redisVerifyCodeKey);
        Response<UserAccessInfo> response = userService.verifyCodeLogin(userAccess, appCode);
        if (!response.isSuccess()) {
            throw new ApplicationException(response.getCode(), response.getMsg());
        }
        UserAccessInfo userAuthAccessInfo = response.getData();

        if (newRegister) {
            userEventTrackService.e_app_register_success();
        } else {
            userEventTrackService.e_app_login_success();
        }
        return registerLoginVOGenerator(userAccess, userAuthAccessInfo, newRegister);
    }

    private void userAppInfoInjection(UserAccess userAccess, RequestBasicInfo requestBasicInfo, String ip) {
        if (null == requestBasicInfo) {
            return;
        }
        String clientId = requestBasicInfo.getClientId();
        PlatformEnum platform = PlatformEnum.OTHER;
        if (StringUtils.isNotEmpty(requestBasicInfo.getAppClient())) {
            platform = PlatformEnum.getEnumByDesc(requestBasicInfo.getAppClient());
            platform = platform == null ? PlatformEnum.OTHER : platform;
        }
        String version = requestBasicInfo.getAppVersion();
        Integer versionCode = requestBasicInfo.getVersionCode();
        String channelName = requestBasicInfo.getChannel();
        String guestId = requestBasicInfo.getMobileImei();
        String packageName = StringUtils.isBlank(requestBasicInfo.getPackageName()) ? "in.dhanadhan.loan.money.cash" : requestBasicInfo.getPackageName();
        UserAppInfo userAppInfo = new UserAppInfo(clientId, platform, version, channelName, guestId, packageName);
        userAppInfo.setIp(ip);
        userAppInfo.setVersionCode(String.valueOf(versionCode));
        userAppInfo.setAppsflyerId(requestBasicInfo.getAppsflyerId());
        userAccess.setUserAppInfo(userAppInfo);
        userAccess.setPackageName(packageName);
    }

    private UserRegisterVO registerLoginVOGenerator(UserAccess userAccess, UserAccessInfo userAuthAccessInfo, boolean newRegister) {
        UserRegisterVO UserRegisterVO = new UserRegisterVO(userAuthAccessInfo);
        if (!apiUserCenterService.bindUserDevice(userAccess)) {
            LOGGER.error("用户手机号:{}设备绑定失败,data:{}", userAccess.getMobile().getMobile(), JsonStream.serialize(userAccess));
        }
        UserRegisterVO.setNewRegister(newRegister);
        return UserRegisterVO;
    }

    public UserRegisterVO passwordLogin(UserAccess userAccess, AppCodeEnum appCodeEnum, String ip) {
        userAppInfoInjection(userAccess, RequestLocalInfo.getRequestBasicInfo(), ip);
        Response<UserAccessInfo> response = userService.passwordLogin(userAccess, appCodeEnum);
        if (!response.isSuccess()) {
            throw new ApplicationException(response.getCode(), response.getMsg());
        }
        UserAccessInfo userAccessInfo = response.getData();
        return registerLoginVOGenerator(userAccess, userAccessInfo, false);
    }

    /**
     * 重置密码
     *
     * @param userAccess
     * @param verifycode
     */
    public void resetUserPassword(UserAccess userAccess, String verifycode) {
        String redisVerifyCodeKey = RedisKeyConsts.VERIFY_CODE_REDIS_KEY_PREFIX + VerifyCodeTypeEnum.VERIFY_TYPE_FORGET_PASSWORD.getName() + userAccess.getMobile().getMobile();
        String redisVerifyCode = redisClient.get(redisVerifyCodeKey);
        if (!verifycode.equals(redisVerifyCode)) {
            throw new ApiErrorException(VerifyCodeErrorCodeEnum.VERIFYCODE_NOT_CORRECT);
        }
        Response<UserAccessInfo> userAccessInfoByMobile = userService.getUserAccessInfoByMobile(userAccess.getMobile().getMobile(), RequestLocalInfo.getRequestBasicInfo().getAppCode());
        if (userAccessInfoByMobile.getData() == null) {
            throw new ApplicationException(UserProfileErrorCodeEnum.USER_PROFILE_NO_EXIST);
        }

        userAccess.setUserCode(userAccessInfoByMobile.getData().getUserCode());
        Response<Boolean> response = userService.updatePassword(userAccess);
        if (!response.isSuccess()) {
            throw new ApiErrorException(response.getMsg());
        }
        redisClient.del(redisVerifyCodeKey);
    }

    /**
     * 设置密码
     *
     * @param userAccess
     */
    public void addUserPassword(UserAccess userAccess) {
        Response<Boolean> response = userService.setPassword(userAccess);
        if (!response.isSuccess()) {
            throw new ApplicationException(response.getCode(), response.getMsg());
        }
    }

    /**
     * 更新密码
     *
     * @param userAccess
     * @param verifycode
     */
    public void updateUserPassword(UserAccess userAccess, String verifycode) {
        Response<User> userResponse = userService.getUserByUserCode(userAccess.getUserCode());
        if (!userResponse.isSuccess()) {
            throw new ApplicationException(userResponse.getCode(), userResponse.getMsg());
        }
        User user = userResponse.getData();
        String mobile = user.getMobile();
        String redisVerifyCodeKey = RedisKeyConsts.VERIFY_CODE_REDIS_KEY_PREFIX + VerifyCodeTypeEnum.VERIFY_TYPE_UPDATE_PASSWORD.getName() + mobile;
        String redisVerifyCode = redisClient.get(redisVerifyCodeKey);
        if (!verifycode.equals(redisVerifyCode)) {
            throw new ApiErrorException(VerifyCodeErrorCodeEnum.VERIFYCODE_NOT_CORRECT);
        }
        Response<Boolean> response = userService.updatePassword(userAccess);
        if (!response.isSuccess()) {
            throw new ApplicationException(response.getCode(), response.getMsg());
        }
        redisClient.del(redisVerifyCodeKey);
    }

    /**
     * 获取登录方式 1验证码 2密码
     *
     * @param mobile
     * @return
     */
    public Integer loginType(String mobile) {
        String appCode = RequestLocalInfo.getRequestBasicInfo().getAppCode();
        Response<UserAccessInfo> userAccessInfoByMobile = userService.getUserAccessInfoByMobile(mobile, appCode);
        if (userAccessInfoByMobile.getData() == null) {
            return LoginTypeEnum.VERIFY_CODE.getCode();
        } else if (userAccessInfoByMobile.getData() != null && StringUtils.isNotBlank(userAccessInfoByMobile.getData().getPassword())) {
            return LoginTypeEnum.PASSWORD.getCode();
        } else {
            return LoginTypeEnum.VERIFY_CODE.getCode();
        }
    }


    /**
     * 更新设备ID
     */
    public void clientIdUpdate() {
        try {
            RequestBasicInfo requestBasicInfo = RequestLocalInfo.getRequestBasicInfo();
            String clientId = requestBasicInfo.getClientId();
            if (StringUtils.isEmpty(clientId)) {
                return;
            }
            UserAccessInfo currentUser = RequestLocalInfo.getCurrentUser();
            if (currentUser == null) {
                return;
            }

            String userCode = currentUser.getUserCode();
            Response<UserBehaviorRegister> registerByUserCode = userBehaviorService.getRegisterByUserCode(userCode);
            UserBehaviorRegister userBehaviorRegister = registerByUserCode.getData();
            if (userBehaviorRegister == null) {
                return;
            }
            String clientIdFromUser = userBehaviorRegister.getClientId();
            if (!clientId.equals(clientIdFromUser)) {
                userBehaviorService.updateOrAddUserClientIdByUserCode(userCode, clientId);
            }

        } catch (Exception e) {
            LOGGER.error("------ product home update clientId exception ------", e);
        }
    }

    public Boolean allActionComplete(String userCode) {
        UserAuthStatusRO userAuthStatusRO = getUserAuthStatus(userCode);
        Boolean kycActionComplete = kycActionComplete(userAuthStatusRO);
        if (Objects.equals(userAuthStatusRO.getBankStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                && Objects.equals(userAuthStatusRO.getBaseInfoStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                && Objects.equals(userAuthStatusRO.getBaseWorkStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                && Objects.equals(userAuthStatusRO.getBaseEmergencyStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                && Objects.equals(userAuthStatusRO.getPanStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                && Objects.equals(userAuthStatusRO.getEmailStatus(), UserAuthStatusEnum.SUCCESS.getCode()) && kycActionComplete) {
            return true;
        }
        return false;
    }

    public boolean kycActionComplete(UserAuthStatusRO userAuthStatusRO) {
        if (Objects.equals(userAuthStatusRO.getAadhaarStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                || Objects.equals(userAuthStatusRO.getPassportStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                || Objects.equals(userAuthStatusRO.getVoterStatus(), UserAuthStatusEnum.SUCCESS.getCode())
                || Objects.equals(userAuthStatusRO.getDriverLicenseStatus(), UserAuthStatusEnum.SUCCESS.getCode())) {
            return true;
        }
        return false;
    }

    public boolean kycAndPanCardComplete(UserAuthStatusRO userAuthStatusRO) {

        if (userAuthStatusRO == null) {
            return false;
        }
        if (this.kycActionComplete(userAuthStatusRO) && Objects.equals(userAuthStatusRO.getPanStatus(), UserAuthStatusEnum.SUCCESS.getCode())) {
            return true;
        }
        return false;
    }

    public Boolean allActionComplete(UserInfo userInfo, UserSocialContact socialContact) {
        UserKycStatusEnum userKycStatusEnum = apiUserCenterService.kycActionComplete(userInfo.getUser().getUserCode());
        boolean kycActionComplete = UserKycStatusEnum.CHECK_SUCCESS.equals(userKycStatusEnum);
        PanStatusEnum panStatusEnum = apiUserCenterService.panActionComplete(userInfo.getUser().getUserCode());
        boolean panComplete = panStatusEnum != null && panStatusEnum.getStatus().equals(PanStatusEnum.YES.getStatus());

        return getUserBankComplete(userInfo.getUser().getUserCode()) &&
                profileActionComplete(userInfo, socialContact) &&
                bankActionComplete(userInfo.getUser().getUserCode()) &&
                kycActionComplete &&
                panComplete &&
                emailComplete(userInfo.getUser().getUserCode());

    }

    public Boolean emailComplete(String userCode) {
        Response<UserAuthEmail> emailRsp = userEmailService.getUserEmail(userCode);
        return emailRsp != null && emailRsp.isSuccess() && emailRsp.getData() != null && StringUtils.isNotBlank(emailRsp.getData().getEmail());
    }

    //银行卡实名认证
    public Boolean getUserBankComplete(String userCode) {
        Response<User> userResponse = userService.getUserByUserCode(userCode);
        if (userResponse.isSuccess()) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    // 基本信息、地址信息、社会联系人信息
    public Boolean personalInformationComplete(UserInfo userInfo, UserSocialContact socialContact) {
        return profileBaseInfoComplete(userInfo, socialContact) &&
                profileEmergencyContactInfoComplete(socialContact);
    }

    // 基本信息、地址信息、社会联系人信息 + 用户工作信息
    public Boolean profileActionComplete(UserInfo userInfo, UserSocialContact socialContact) {
        return profileBaseInfoComplete(userInfo, socialContact) &&
                profileWorkInfoComplete(userInfo) &&
                profileEmergencyContactInfoComplete(socialContact);
    }

    public Boolean bankActionComplete(String userCode) {
        Response<UserBankInfo> userBankInfoResponse = userBankService.getByUserCode(userCode);
        UserBankInfo userBank = userBankInfoResponse.getData();
        return null != userBank && userBank.getStatus() == 1;
    }

    public Boolean profileBaseInfoComplete(UserInfo userInfo, UserSocialContact socialContact) {

        UserBase userBase = userInfo.getUserBase();
        UserResident resident = userInfo.getUserResident();
        if (userBase != null
                && userBase.getMarriedStatus() != null
                && StringUtils.isNotBlank(userBase.getFirstName())
                && StringUtils.isNotBlank(userBase.getLastName())
                && StringUtils.isNotBlank(userBase.getFatherName())
                && StringUtils.isNotBlank(userBase.getMotherName())
                && userBase.getGender() != null
                && userBase.getGender() > 0
                && userBase.getUsages() != null
                && resident != null
                && resident.getAddress() != null
                && StringUtils.isNotBlank(resident.getPermanentAddress())
                && StringUtils.isNotBlank(resident.getPermanentPinCode())
        ) {
            return true;
        }
        return false;
    }

    public Boolean profileWorkInfoComplete(UserInfo userInfo) {
        UserWork userWork = userInfo.getUserWork();

        if (null != userWork && StringUtils.isNotEmpty(userWork.getCompanyName())
                && userWork.getCareerType() != null
                && StringUtils.isNotEmpty(userWork.getFromWhen())
                && userWork.getSalary() != null
        ) {
            return true;
        }
        return false;
    }

    public Boolean profileEmergencyContactInfoComplete(UserSocialContact socialContact) {

        UserEmergencyContact userEmergencyContact = socialContact.getUserEmergencyContact();
        if (null != userEmergencyContact
                && null != userEmergencyContact.getUserFamilyContact()
                && null != userEmergencyContact.getUserFriendContact()) {
            return true;
        }
        return false;
    }

    /**
     * 保存gps
     *
     * @param gpsDTO
     */
    public void saveGps(GpsDTO gpsDTO) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        UserGps userGps = new UserGps();
        userGps.setLat(gpsDTO.getLat());
        userGps.setLng(gpsDTO.getLng());
        userGps.setArea(gpsDTO.getArea());
        userBehaviorService.addUserGps(userCode, userGps);
        LOGGER.info("##################### gps　upload success userCode：{}#####################", userCode);
    }

    /**
     * 保存紧急联系人
     *
     * @param jsonObject
     */
    public void saveContact(JSONObject jsonObject) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        String data = jsonObject.getString("data");
        //gzip解压
        String jsonData = ZipUtils.gunzip(data);
//        LOGGER.info("==== 解压后的data:{} ===", jsonData);
        AppVo appVo = appUtils.getAppVo();
        String filePath = "moveDeviceContact/";
        String smsFilePath = "moveSms/";
        if (apolloConfigUtil.isServerTest()) {
            filePath += "test/";
            smsFilePath += "test/";
        }
        filePath += RequestLocalInfo.getCurrentUser().getUserCode() + "_" + System.currentTimeMillis() + ".json";
        String url = apolloConfigUtil.getOssBaseUrl() + ossService.uploadFile(filePath, jsonData);
        LOGGER.info("#####################userCode：{}, 上传AmazonS3通讯录地址为：{}#####################", userCode, url);

        JSONObject jsonObjectData = JSONObject.parseObject(jsonData);
        JSONArray smsList = jsonObjectData.getJSONArray("smsList");
        String smsUrl = null;
        if (smsList != null && !smsList.isEmpty()) {
            JSONObject smsObject = new JSONObject();
            smsObject.put("smsList", smsList);
            smsFilePath += "SMS_" + RequestLocalInfo.getCurrentUser().getUserCode() + "_" + System.currentTimeMillis() + ".json";
            smsUrl = apolloConfigUtil.getOssBaseUrl() + ossService.uploadFile(smsFilePath, smsObject.toJSONString());
            LOGGER.info("#####################userCode：{},上传到AmazonS3短信记录地址为：{}#####################", userCode, smsUrl);
        }
        apiUserCenterService.saveUserContactInfo(userCode, url, smsUrl, appVo.getAppCode());
    }

    /**
     * 保存短信记录
     *
     * @param jsonObject
     */
    public void saveSms(JSONObject jsonObject) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        String data = jsonObject.getString("data");
        //gzip解压
        String jsonData = ZipUtils.gunzip(data);
        AppVo appVo = appUtils.getAppVo();
        String filePath = "sms/";
        if (apolloConfigUtil.isServerTest()) {
            filePath += "test/";
        }
        filePath += "SMS_" + RequestLocalInfo.getCurrentUser().getUserCode() + "_" + System.currentTimeMillis() + ".json";
        String url = apolloConfigUtil.getOssBaseUrl() + ossService.uploadFile(filePath, jsonData);
        LOGGER.info("#####################userCode：{},上传到AmazonS3短信记录地址为：{}#####################", userCode, url);
        UserSocialContact userSocialContact = new UserSocialContact();
        userSocialContact.setDeviceContact(url);
        apiUserCenterService.saveUserContactInfo(new UserContact().setUserCode(userCode), userSocialContact, appVo.getAppCode());
    }

    /**
     * 保存数美信息
     */
    public void addShumeiDevice(String userCode, String data) {
        JSONObject resultJsonObject = JSONObject.parseObject(data);
        //smid 国外可能为空
        if (null == resultJsonObject) {
            LOGGER.info("插入数美数据异常，resultJsonObject为空:userCode{}", userCode);
            throw new ApiErrorException(UserProfileErrorCodeEnum.USER_PROFILE_SM_DATA_ERROR);
        }

        String fingerprintData = data;
        String smId = resultJsonObject.getString("smid");

        PlatformEnum platformEnum = PlatformEnum.getEnumByDesc(RequestLocalInfo.getRequestBasicInfo().getAppClient());
        Long currentTime = System.currentTimeMillis();
        String filename = "moveFingerprintData/fingerprintData_" + userCode + "_" + currentTime + ".json";
        String fingerprintDataUrl = apolloConfigUtil.getOssBaseUrl() + ossService.uploadFile(filename, fingerprintData);
        ShumeiDevice shumeiDevice = new ShumeiDevice(smId, fingerprintDataUrl, platformEnum);
        userDeviceService.addShumeiInfo(userCode, shumeiDevice);
        LOGGER.info("==== 数美信息保存成功 fingerprintDataUrl:{}===", fingerprintDataUrl);
    }

    public void saveAlgo360(JSONObject jsonObject) {
        try {
            String data = jsonObject.getString("data");
            String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
            LOGGER.info("== algo360:{} ==", data);
            if (StringUtils.isNotBlank(data)) {
                JSONObject dataObject = JSONObject.parseObject(data);
                boolean status = dataObject.getBoolean("dataSynced");
                UserAuthSmsHistory userAuthSmsHistory = new UserAuthSmsHistory()
                        .setUserCode(userCode)
                        .setSdkResult(data)
                        .setStatus(status ? 1 : 0)
                        .setType(UserAuthSmsTypeEnum.ALGO_360.getType());
                userAuthSmsService.addUserAuthSmsHistory(userAuthSmsHistory);

                LOGGER.info("algo360 init success userCode:{},status:{}", userCode, status);
                if (status) {//上报成功
                    UserAuthSms userAuthSms = new UserAuthSms()
                            .setType(UserAuthSmsTypeEnum.ALGO_360.getType())
                            .setStatus(BasicErrorCodeEnum.SUCCESS.getCode())
                            .setUserCode(userCode);
                    userAuthSmsService.addUserAuthSms(userAuthSms);

                }
            }
        } catch (Exception e) {
            LOGGER.error("上报algo360错误:e" + e);
        }
    }

    /**
     * 个人中心
     *
     * @return
     */
    public UserInfoAccountVO personalCenter(HttpServletRequest request) {

        UserInfoAccountVO userInfoAccountVO = new UserInfoAccountVO();
        if (null != RequestLocalInfo.getCurrentUser() && StringUtils.isNotEmpty(RequestLocalInfo.getCurrentUser().getUserCode())) {
            UserProfile userProfile = this.getUserProfileInfo(RequestLocalInfo.getCurrentUser().getUserCode());
            userInfoAccountVO.setRealName(StringUtils.isBlank(userProfile.getUserName()) ? SensitiveInfoUtils.mobilePhone(userProfile.getMobile()) : userProfile.getUserName());
            userInfoAccountVO.setMobile(SensitiveInfoUtils.mobilePhone(userProfile.getMobile()));
            userInfoAccountVO.setAvatar(userProfile.getAvatar());
        }
        userInfoAccountVO.setLoanOrderList(this.buildLoanList());
        userInfoAccountVO.setToolsList(this.getAccountList(request));
        return userInfoAccountVO;
    }

    public UserProfile getUserProfileInfo(String userCode) {
        Response<UserInfo> userInfoRs = userInfoService.getUserInfoByUserCode(userCode);
        UserInfo userInfo = userInfoRs.getData();
        Response<UserLoginInfo> userLoginInfoResponse = userService.getUserLoginInfo(userCode);
        UserLoginInfo userLoginInfo = userLoginInfoResponse.getData();
        return buildUserProfile(userInfo.getUser(), userInfo.getUserBase(), userLoginInfo);
    }

    private UserProfile buildUserProfile(User user, UserBase userBase, UserLoginInfo userLoginInfo) {
        UserProfile userProfile = new UserProfile();
        userProfile.setUserName(user.getName());
        userProfile.setIdentityNo(user.getIdentityNo());
        userProfile.setMobile(user.getMobile());
        userProfile.setAvatar(userLoginInfo.getAvatar());
        if (userBase != null) {
            userProfile.setEmail(Strings.nullToEmpty(userBase.getEmail()));
            if (userBase.getEducation() != null) {
                UserEducationEnum userEducationEnum = UserEducationEnum.getEnumByType(userBase.getEducation());
                userProfile.setUserEducationEnum(userEducationEnum);
            }
            if (userBase.getMarriedStatus() != null) {
                UserMarriageEnum userMarriageEnum = UserMarriageEnum.getEnumByType(userBase.getMarriedStatus());
                userProfile.setUserMarriageEnum(userMarriageEnum);
            }
        }
        return userProfile;
    }

    /**
     * 个人中心Tools
     *
     * @return
     */
    public List<UserAccountVO> getAccountList(HttpServletRequest request) {
        String menuInfo = apolloConfigUtil.getUserInfoMenu();
        JSONObject jsonObject = JSONObject.parseObject(menuInfo);
        String version = "V" + RequestLocalInfo.getRequestBasicInfo().getAppVersion();
        String packageName = RequestLocalInfo.getRequestBasicInfo().getPackageName();
        List<UserAccountVO> list = Lists.newArrayList();
        UserAccountVO notice;
        UserAccountVO faq;
        UserAccountVO aboutUs;
        UserAccountVO contactUs;
        UserAccountVO logout;
        if (packageName.equals(PackageNameEnum.CASHMall.getPackageName())) {
            notice = new UserAccountVO(
                    UserAccountEnum.NOTICE.getTitle(),
                    UserAccountEnum.NOTICE.getNewImgUrl(),
                    UserAccountEnum.NOTICE.getJumpUrl()
            );
            faq = new UserAccountVO(
                    UserAccountEnum.FAQ.getTitle(),
                    UserAccountEnum.FAQ.getNewImgUrl(),
                    "https://www.cash-mall.in/faqs"
            );
            aboutUs = new UserAccountVO(
                    UserAccountEnum.ABOUT_US.getTitle(),
                    UserAccountEnum.ABOUT_US.getNewImgUrl(),
                    "https://www.cash-mall.in/"
            );
            contactUs = new UserAccountVO(
                    UserAccountEnum.CONTACT_US.getTitle(),
                    UserAccountEnum.CONTACT_US.getNewImgUrl(),
                    "https://www.cash-mall.in/"
            );
            logout = new UserAccountVO(
                    UserAccountEnum.LOG_OUT.getTitle(),
                    UserAccountEnum.LOG_OUT.getNewImgUrl(),
                    UserAccountEnum.LOG_OUT.getJumpUrl()
            );
        }else if (packageName.equals(PackageNameEnum.RUPEEMAMA.getPackageName())) {
            notice = new UserAccountVO(
                    UserAccountEnum.NOTICE.getTitle(),
                    UserAccountEnum.NOTICE.getNewImgUrl(),
                    UserAccountEnum.NOTICE.getJumpUrl()
            );
            faq = new UserAccountVO(
                    UserAccountEnum.FAQ.getTitle(),
                    UserAccountEnum.FAQ.getNewImgUrl(),
                    "http://www.rupee-mama.in/faqs"
            );
            aboutUs = new UserAccountVO(
                    UserAccountEnum.ABOUT_US.getTitle(),
                    UserAccountEnum.ABOUT_US.getNewImgUrl(),
                    "http://www.rupee-mama.in"
            );
            contactUs = new UserAccountVO(
                    UserAccountEnum.CONTACT_US.getTitle(),
                    UserAccountEnum.CONTACT_US.getNewImgUrl(),
                    "http://www.rupee-mama.in"
            );
            logout = new UserAccountVO(
                    UserAccountEnum.LOG_OUT.getTitle(),
                    UserAccountEnum.LOG_OUT.getNewImgUrl(),
                    UserAccountEnum.LOG_OUT.getJumpUrl()
            );
        } else {

            notice = new UserAccountVO(
                    UserAccountEnum.NOTICE.getTitle(),
                    UserAccountEnum.NOTICE.getImgUrl(),
//                appUtils.getNoticeIcon(packageName, jsonObject),
                    UserAccountEnum.NOTICE.getJumpUrl()
            );
            faq = new UserAccountVO(
                    UserAccountEnum.FAQ.getTitle(),
                    UserAccountEnum.FAQ.getImgUrl(),
//                appUtils.getFAQSIcon(packageName, jsonObject),
                    "http://www.rupee-mama.in/faqs"
//                appUtils.getFAQS(packageName, jsonObject)
            );
            aboutUs = new UserAccountVO(
                    UserAccountEnum.ABOUT_US.getTitle(),
                    UserAccountEnum.ABOUT_US.getImgUrl(),
//                appUtils.getUserAboutUrlIcon(packageName, jsonObject),
                    "http://www.rupee-mama.in"
//                appUtils.getUserAboutUrl(packageName, jsonObject) + "?version=" + version
            );
            contactUs = new UserAccountVO(
                    UserAccountEnum.CONTACT_US.getTitle(),
                    UserAccountEnum.CONTACT_US.getImgUrl(),
//                appUtils.getContactUsIcon(packageName, jsonObject),
                    "http://www.rupee-mama.in"
//                appUtils.getContactUs(packageName, jsonObject) + "?host=" + apolloConfigUtil.getApiWebPath() + "&basicParams=" + (request != null ? request.getHeader("basicParams") : "")
            );
            logout = new UserAccountVO(
                    UserAccountEnum.LOG_OUT.getTitle(),
                    UserAccountEnum.LOG_OUT.getImgUrl(),
//                appUtils.getLogoutIcon(packageName, jsonObject),
                    UserAccountEnum.LOG_OUT.getJumpUrl()
            );
        }

        list.add(notice);
        list.add(aboutUs);
        list.add(faq);
        list.add(contactUs);
        list.add(logout);
        return list;
    }

    private List<UserAccountVO> buildLoanList() {
        List<UserAccountVO> tools = Lists.newArrayList();
        UserAccountVO loanRecord = new UserAccountVO(
                UserToolsEnum.LOAN_RECORD.getTitle(),
                UserToolsEnum.LOAN_RECORD.getImgUrl(),
                UserToolsEnum.LOAN_RECORD.getJumpUrl()
        );
        UserAccountVO profile = new UserAccountVO(
                UserToolsEnum.PROFILE.getTitle(),
                UserToolsEnum.PROFILE.getImgUrl(),
                UserToolsEnum.PROFILE.getJumpUrl()
        );
        tools.add(loanRecord);
        tools.add(profile);
        return tools;
    }

    /**
     * 保存头像
     *
     * @param userCode
     * @param avatar
     * @param nickname
     */
    public void saveUserAvatar(String userCode, String avatar, String nickname) {
        Response<Boolean> response = userService.updateUserAvatar(userCode, OSSFixUtils.fixOssUrl(avatar), nickname);
        if (!response.isSuccess()) {
            throw new ApiErrorException(response.getMsg());
        }
    }

    public UserCreditVO userCredit() {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        UserCreditVO userCreditVO = new UserCreditVO();
        String appCode = RequestLocalInfo.getRequestBasicInfo().getAppCode();
        String packageName = RequestLocalInfo.getRequestBasicInfo().getPackageName();
        List<ProductCategory> categories = ordersHandler.getProductCategoryList(packageName, appCode);
        if (!apiUserCenterService.isCreditComplete(userCode)) {
            apiUserCenterService.initializationQuota(userCode);
        }
        String jumpUrl = "";
        if (CollectionUtils.isNotEmpty(categories) && categories.size() == 1) {
            jumpUrl = JumpRouterEnum.PRODUCT_DETAIL.getJumpUrl() + "?categoryCode=" + categories.get(0).getCode();
        } else {
            jumpUrl = JumpRouterEnum.HOME_PRODUCT.getJumpUrl();
        }
        userCreditVO.setCreditStatus(1);
        userCreditVO.setJumpUrl(jumpUrl);
        userCreditVO.setAmount("₹" + apolloConfigUtil.getCreditAmount());
        userCreditVO.setNeedALGO360Verify(configHandler.needAlgo360Verify(userCode));
        userCreditVO.setPermissionsInfo(configHandler.getPermissionsInfoOfSmsFromString());
        if (redisClient.get(RedisKeyConsts.SMS_REPORT_KEY, userCode) != null) {
            LOGGER.info("== SMS_REPORT_KEY is exist userCode:{} ==", userCode);
            userCreditVO.setSmsReportInfo(redisClient.get(RedisKeyConsts.SMS_REPORT_KEY, userCode));
            return userCreditVO;
        }
        SmsReportInfo smsReportInfo = new SmsReportInfo();
        smsReportInfo.setHighScore("310");
        UserWork userWork = apiUserCenterService.getUserWorkInfoByUserCode(userCode);
        if (userWork != null) {
            String salary = UserSalaryEnum.getEnumByType(userWork.getSalary()).getDesc();
            Integer income = 0;
            if (userWork.getSalary() == UserSalaryEnum.UNDER_5000.getType()) {
                income = 5000;
            }
            if (userWork.getSalary() == UserSalaryEnum.MORE_THAN_50000.getType()) {
                income = 50000;
            }
            String[] incomes = salary.replaceAll("₹", "").replaceAll(",", "").split("-");
            income = (userWork.getSalary() != UserSalaryEnum.MORE_THAN_50000.getType() && userWork.getSalary() != UserSalaryEnum.UNDER_5000.getType()) ?
                    RandomUtils.nextInt(Integer.valueOf(incomes[0]), Integer.valueOf(incomes[1])) : income;
            smsReportInfo.setIncomeMonthlyAverage("₹" + income);
            Integer wagePct = RandomUtils.nextInt(85, 95);
            smsReportInfo.setIncomeWagePct(wagePct + "%");
            smsReportInfo.setIncomeOtherPct((100 - wagePct) + "%");
            BigDecimal spending = DecimalUtils.mul(new BigDecimal(RandomUtils.nextDouble(0.2d, 0.3d)), new BigDecimal(income));
            smsReportInfo.setSpendingMonthlyAverage("₹" + spending.intValue());
            Integer bankCardPct = RandomUtils.nextInt(85, 95);
            smsReportInfo.setSpendingBankCardPct(bankCardPct + "%");
            smsReportInfo.setSpendingCreditCardPct((100 - bankCardPct) + "%");
        }
        Integer score = RandomUtils.nextInt(240, 310);
        smsReportInfo.setScore(score.toString());
        smsReportInfo.setReportRank(SmsReportUtils.getSmsReportRank(score));
        UserContactAddressBook userContactAddressBook = apiUserCenterService.getUserContactInfo(userCode);
        if (userContactAddressBook == null || StringUtils.isBlank(userContactAddressBook.getContactUrl())) {
            smsReportInfo.setScore("0");
            smsReportInfo.setReportRank(SmsReportRankEnum.FAIL.getRank());
        }
        redisClient.set(RedisKeyConsts.SMS_REPORT_KEY, smsReportInfo, TimeConsts.ONE_MONTH, userCode);
        userCreditVO.setSmsReportInfo(smsReportInfo);
        return userCreditVO;
    }

    public String getJumpUrl(boolean profileFinished, String userCode, String productCategory, String merchantCode) {
        String jumpUrl;
        if (!profileFinished) {
            jumpUrl = JumpRouterEnum.ACTION_PROFILE.getJumpUrl();
        } else {
            if (!apiUserCenterService.isCreditComplete(userCode)) {
                jumpUrl = JumpRouterEnum.CREDIT_AUDIT.getJumpUrl();
            } else {
                if (StringUtils.isNotBlank(productCategory) && StringUtils.isNotBlank(merchantCode)) {
                    jumpUrl = JumpRouterEnum.PRODUCT_DETAIL.getJumpUrl() + "?categoryCode=" + productCategory + "&merchantCode=" + merchantCode;
                } else {
                    jumpUrl = JumpRouterEnum.HOME_PRODUCT.getJumpUrl();
                }
            }
        }
        return jumpUrl;
    }

    public String getJumpUrl(boolean profileFinished, String userCode) {
        String jumpUrl = "";
        if (!profileFinished) {
            jumpUrl = JumpRouterEnum.ACTION_PROFILE.getJumpUrl();
        } else {
            if (!apiUserCenterService.isCreditComplete(userCode)) {
                jumpUrl = JumpRouterEnum.CREDIT_AUDIT.getJumpUrl();
            } else {
                jumpUrl = JumpRouterEnum.HOME_PRODUCT.getJumpUrl();
            }
        }
        return jumpUrl;
    }

    public SmsReportInfo report() {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        boolean profileFinished = allActionComplete(userCode);
        String jumpUrl = getJumpUrl(profileFinished, userCode);
        SmsReportInfo smsReport = redisClient.get(RedisKeyConsts.SMS_REPORT_KEY, userCode);
        if (smsReport != null) {
            if (!Objects.equals(smsReport.getJumpUrl(), jumpUrl)) {
                smsReport.setJumpUrl(jumpUrl);
            }
            LOGGER.info("== SMS_REPORT_KEY is exist userCode:{} ==", userCode);
            return smsReport;
        }
        UserContactAddressBook userContactAddressBook = apiUserCenterService.getUserContactInfo(userCode);
        if (userContactAddressBook == null || StringUtils.isBlank(userContactAddressBook.getContactUrl())) {
            return null;
        }
        SmsReportInfo smsReportInfo = new SmsReportInfo();
        smsReportInfo.setHighScore("310");
        Integer income = RandomUtils.nextInt(20000, 40000);
        smsReportInfo.setIncomeMonthlyAverage("₹" + income);
        Integer wagePct = RandomUtils.nextInt(85, 95);
        smsReportInfo.setIncomeWagePct(wagePct + "%");
        smsReportInfo.setIncomeOtherPct((100 - wagePct) + "%");
        BigDecimal spending = DecimalUtils.mul(new BigDecimal(RandomUtils.nextDouble(0.2d, 0.3d)), new BigDecimal(income));
        smsReportInfo.setSpendingMonthlyAverage("₹" + spending.intValue());
        Integer bankCardPct = RandomUtils.nextInt(85, 95);
        smsReportInfo.setSpendingBankCardPct(bankCardPct + "%");
        smsReportInfo.setSpendingCreditCardPct((100 - bankCardPct) + "%");

        Integer score = RandomUtils.nextInt(240, 310);
        smsReportInfo.setScore(score.toString());
        smsReportInfo.setReportRank(SmsReportUtils.getSmsReportRank(score));
        if (userContactAddressBook == null || StringUtils.isBlank(userContactAddressBook.getContactUrl())) {
            smsReportInfo.setScore("0");
            smsReportInfo.setReportRank(SmsReportRankEnum.FAIL.getRank());
        }
        smsReportInfo.setJumpUrl(jumpUrl);
        redisClient.set(RedisKeyConsts.SMS_REPORT_KEY, smsReportInfo, TimeConsts.ONE_MONTH, userCode);
        return smsReportInfo;
    }

    /**
     * 更新状态
     *
     * @param userAuthStatusEnum
     * @param userAuthEnum
     * @param userCode
     */
    public void updateUserAuthStatus(UserAuthStatusEnum userAuthStatusEnum, UserAuthEnum userAuthEnum, String userCode) {
        try {
            UserAuthRO userAuthRO = new UserAuthRO();
            userAuthRO.setAppCode("5");
            userAuthRO.setUserCode(userCode);
            userAuthRO.setBiz(BusinessTypeENUM.XJD.getCode());
            userAuthRO.setUserAuthEnum(userAuthEnum);
            userAuthRO.setUserAuthStatusEnum(userAuthStatusEnum);
            userAuthServiceFacade.updateUserAuthStatus(userAuthRO);
        } catch (Exception e) {
            LOGGER.error("updateUserAuthStatus失败,userCode:{},e:{}", userCode, e);
        }
    }

    /**
     * 查询状态
     *
     * @param userCode
     * @return
     */
    public UserAuthStatusRO getUserAuthStatus(String userCode) {
        if (com.fqgj.common.utils.StringUtils.isEmpty(userCode)) {
            return null;
        }
        UserBaseQueryRO userBaseQueryRO = new UserBaseQueryRO();
        userBaseQueryRO.setAppCode("5");
        userBaseQueryRO.setBiz(BusinessTypeENUM.XJD.getCode());
        userBaseQueryRO.setUserCode(userCode);
        Response<UserAuthStatusRO> response = userAuthServiceFacade.queryUserAuthStatus(userBaseQueryRO);
        if (response == null || !response.isSuccess()) {
            throw new ApplicationException("Query failed");
        }
        LOGGER.info("getUserAuthStatus response:{} ", JSONObject.toJSONString(response));
        return response.getData();
    }

    /**
     * 是否新用户
     *
     * @param userCode
     * @return
     */
    public boolean isNewUser(String userCode) {
        UserAuthStatusRO userAuthStatusRO = getUserAuthStatus(userCode);
        if (userAuthStatusRO == null) {
            return true;
        }
        if (Objects.equals(userAuthStatusRO.getIsOldUser(), UserAuthStatusEnum.SUCCESS.getCode())) {
            return false;
        }
        return true;
    }

    /**
     * 是否新用户
     *
     * @param userCode
     * @return
     */
    public UserAuthInfoVO getUserAuthInfo(String userCode) {
        UserAuthInfoVO userAuthInfoVO = new UserAuthInfoVO();
        userAuthInfoVO.setNewUser(true);
        userAuthInfoVO.setAuthDate(new Date());
        UserAuthStatusRO userAuthStatusRO = getUserAuthStatus(userCode);
        if (userAuthStatusRO == null) {
            return userAuthInfoVO;
        }
        if (Objects.equals(userAuthStatusRO.getIsOldUser(), UserAuthStatusEnum.SUCCESS.getCode())) {
            userAuthInfoVO.setNewUser(false);
        }
        if (userAuthStatusRO.getGmtCreate() != null) {
            userAuthInfoVO.setAuthDate(userAuthStatusRO.getGmtCreate());
        }
        return userAuthInfoVO;
    }

    /**
     * 是否跳转到短信分析页面
     *
     * @param userCode
     * @return
     */
    public boolean jumpSmsReport(String userCode) {
        if (appUtils.getAppConfig().isSmsReportSwitch()) {
            if (redisClient.get(RedisKeyConsts.SMS_REPORT_KEY, userCode) != null) {
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    }

    /**
     * 根据系统中的用户额度来展示不同类目
     *
     * @param userCode
     * @param productCategories
     * @return
     */
    public PlatformUserOrderInfo getPlatformOrderInfo(String userCode, List<ProductCategory> productCategories) {

        String packageName = StringUtils.isBlank(RequestLocalInfo.getRequestBasicInfo().getPackageName()) ? PackageNameEnum.DHANADHAN.getPackageName() : RequestLocalInfo.getRequestBasicInfo().getPackageName();
        if (PackageNameEnum.LOANZONE.getPackageName().equalsIgnoreCase(packageName)) {
            List<ProductCategory> newUserProductCategories = productCategories.stream().filter(productCategory -> ProductCategoryEnum.LOAN_ZONE.getCode().equalsIgnoreCase(productCategory.getCode())).collect(Collectors.toList());
            PlatformUserOrderInfo platformUserOrderInfo = new PlatformUserOrderInfo();
            platformUserOrderInfo.setProductCategory(newUserProductCategories.get(0));
            return platformUserOrderInfo;
        } else {
            List<ProductCategory> newUserProductCategories = productCategories;
            if (PackageNameEnum.CREDFOX.getPackageName().equalsIgnoreCase(packageName) || PackageNameEnum.DHANADHAN.getPackageName().equalsIgnoreCase(packageName)) {
                QueryTradeRORequest queryUserLatestTradeRequest = new QueryTradeRORequest();
                queryUserLatestTradeRequest.setUserCode(userCode);
                queryUserLatestTradeRequest.setProductCategory(null);
                Response<UserTradeROListResponse> response = tradeQueryService.queryUserTradeList(queryUserLatestTradeRequest);
                List<TradeVO> tradeList = response.getData() != null ? response.getData().getTradeList() : Lists.newArrayList();
                tradeList = tradeList.stream().filter(tradeVO -> (tradeVO.getProductCategory().equalsIgnoreCase(ProductCategoryEnum.DDD_V7_NEW.getCode()) || tradeVO.getProductCategory().equalsIgnoreCase(ProductCategoryEnum.DDDV7.getCode()))).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(tradeList)) {
                    for (TradeVO tradeVO : tradeList) {
                        if (tradeVO.getProductCategory().equalsIgnoreCase(ProductCategoryEnum.DDD_V7_NEW.getCode())) {
                            newUserProductCategories = productCategories.stream().filter(productCategory -> ProductCategoryEnum.DDD_V7_NEW.getCode().equalsIgnoreCase(productCategory.getCode())).collect(Collectors.toList());
                            break;
                        } else if (tradeVO.getProductCategory().equalsIgnoreCase(ProductCategoryEnum.DDDV7.getCode())) {
                            newUserProductCategories = productCategories.stream().filter(productCategory -> ProductCategoryEnum.DDDV7.getCode().equalsIgnoreCase(productCategory.getCode())).collect(Collectors.toList());
                            break;
                        }
                    }
                } else {
                    if (PackageNameEnum.CREDFOX.getPackageName().equalsIgnoreCase(packageName)) {
                        newUserProductCategories = productCategories.stream().filter(productCategory -> ProductCategoryEnum.DDD_V7_NEW.getCode().equalsIgnoreCase(productCategory.getCode())).collect(Collectors.toList());
                    } else if (PackageNameEnum.DHANADHAN.getPackageName().equalsIgnoreCase(packageName)) {
                        newUserProductCategories = productCategories.stream().filter(productCategory -> ProductCategoryEnum.DDDV7.getCode().equalsIgnoreCase(productCategory.getCode())).collect(Collectors.toList());
                    }
                }
            }
            PlatformUserOrderInfo platformUserOrderInfo = new PlatformUserOrderInfo();
            platformUserOrderInfo.setProductCategory(newUserProductCategories.get(0));
            return platformUserOrderInfo;
        }


        /*UserPanInfo userPanInfo = apiUserCenterService.getUserPanInfo(userCode);
        if(userPanInfo == null){
            platformUserOrderInfo.setProductCategory(newUserProductCategories.get(0));
            return platformUserOrderInfo;
        }
        LOGGER.info("== user panCardNo:{},userCode:{} ==", userPanInfo.getCardNo(), userCode);
        List<UserPanInfo> userPanInfoList = apiUserCenterService.getUserPanInfoList(userPanInfo.getCardNo());
        if(CollectionUtils.isNotEmpty(userPanInfoList) && userPanInfoList.size() == 1){
            LOGGER.info("=== new user show 7 days products, userCode:{} ===", userCode);
            platformUserOrderInfo.setProductCategory(newUserProductCategories.get(0));
            return platformUserOrderInfo;
        }else{
            List<String> userCodes = userPanInfoList.stream().map(UserPanInfo::getUserCode).collect(Collectors.toList());
            List<BillVO> billList = apiTradeService.getBillListByUserCodes(userCodes);
            if(CollectionUtils.isEmpty(billList)){
                LOGGER.info("user has no bill userCode:{},panCardNo:{}", userCode, userPanInfo.getCardNo());
                platformUserOrderInfo.setProductCategory(newUserProductCategories.get(0));
                return platformUserOrderInfo;
            }
            LOGGER.info("== the user billList:{} == ", JSONObject.toJSONString(billList));
            List<BillVO> bills = billList.stream().filter(billVO -> (!Objects.equals(billVO.getProductCategory(), ProductCategoryEnum.DDDV6.getCode()) || !Objects.equals(billVO.getProductCategory(), ProductCategoryEnum.DDDV7.getCode()))).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(bills)){
                platformUserOrderInfo.setProductCategory(newUserProductCategories.get(0));
                return platformUserOrderInfo;
            }
            boolean hasOverdue7Days = billList.stream().filter(billVO -> billVO.getOverdueDays() > 7).count() > 0 ? true : false;
            if(hasOverdue7Days){
                LOGGER.info("=== old user has overdue over 7 days bill show 14 days products, userCodes:{},userCode:{} ===", JSONObject.toJSONString(userCodes), userCode);
                platformUserOrderInfo.setProductCategory(newUserProductCategories.get(0));
            }else{
                List<UserQuotaResponse> userQuotaList = apiUserCenterService.getUserQuotaList(userCodes);
                UserQuotaResponse userQuotaResponse = userQuotaList.stream().max(Comparator.comparingInt(UserQuotaResponse::getRiskLevel)).get();
                //设置成老用户额度
                apiUserCenterService.initializationQuota(userCode, oldUserProductCategories.get(0), userQuotaResponse.getRiskLevel());
                platformUserOrderInfo.setUserRiskLevel(userQuotaResponse.getRiskLevel());
                platformUserOrderInfo.setProductCategory(oldUserProductCategories.get(0));
                LOGGER.info("=== old user show 14 days products, userCode:{},riskLevel:{} ===", userCode, userQuotaResponse.getRiskLevel());
            }
            return platformUserOrderInfo;
        }*/
    }

    /**
     * 校验IFSC
     *
     * @param jsonObject
     * @return
     */
    public IFSCCheckResponse checkBankIFSC(JSONObject jsonObject) {
        String ifscCode = jsonObject.getString("ifsccode");
        if (StringUtils.isEmpty(ifscCode)) {
            throw new ApplicationException("IFSC Code can't be empty");
        }
        ifscCode = ifscCode.trim().replaceAll("\\s*", "");
        IFSCCheckResponse ifscCheckResponse = ifscServiceProvider.ifscCheck(ifscCode);
        if (!ifscCheckResponse.isCheckSuccess() || StringUtils.isEmpty(ifscCheckResponse.getBank())) {
            throw new ApplicationException("IFSC Code is invalid, Please confirm and re-enter");
        }
        return ifscCheckResponse;
    }

    public UserAccessInfo getUserAccessInfoByUserCode(String userCode) {
        Response<UserAccessInfo> response = userService.getUserAccessInfoByUserCode(userCode);
        if (!response.isSuccess()) {
            return null;
        }
        return userService.getUserAccessInfoByUserCode(userCode).getData();
    }


    public void saveUserFeedBack(String userCode, String title, String content, String imageUrl) {
        Response<User> userByUserCode = userService.getUserByUserCode(userCode);
        User user = userByUserCode.getData();
        Response<UserAuthEmail> userEmail = userEmailService.getUserEmail(userCode);
        UserAuthEmail email = userEmail.getData();
        UserFeedBackRequest request = new UserFeedBackRequest();
        request.setUserCode(userCode);
        request.setMobile(user != null ? user.getMobile() : "");
        request.setEmail(email != null ? email.getEmail() : "");
        request.setName(user != null ? user.getName() : "");
        request.setTitle(StringUtils.isEmpty(title) ? "APP Feedback" : title);
        request.setContent(content);
        request.setImageUrl(imageUrl);
        Response<Boolean> response = userBehaviorService.saveFeedback(request);
        LOGGER.info("============= feedback response:{} =============", JSONObject.toJSONString(response));
        if (!response.isSuccess()) {
            throw new ApplicationException(BasicErrorCodeEnum.INTERNAL_SERVER_ERROR);
        }
    }

    public List<UserFeedbackVO> feedbackList() {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        Response<UserFeedbackList> userFeedbackListByUserCode = userBehaviorService.getUserFeedbackListByUserCode(userCode);
        List<UserFeedbackVO> list = Lists.newArrayList();
        if (userFeedbackListByUserCode.getData() != null && CollectionUtils.isNotEmpty(userFeedbackListByUserCode.getData().getUserFeedBacks())) {
            List<UserFeedBackRO> userFeedBacks = userFeedbackListByUserCode.getData().getUserFeedBacks();
            for (UserFeedBackRO userFeedBackRO : userFeedBacks) {
                UserFeedbackVO userFeedbackVO = new UserFeedbackVO();
                userFeedbackVO.setId(userFeedBackRO.getId());
                userFeedbackVO.setCustomerType(userFeedBackRO.getAnswerType());
                userFeedbackVO.setReplyDate(DateUtil.getDateTime(userFeedBackRO.getSubmitDate()));
                userFeedbackVO.setReplyContent(userFeedBackRO.getContent());
                userFeedbackVO.setImageUrl(userFeedBackRO.getImageUrl());
                if (FeedbackTypeEnum.CUSTOMER_SERVICE.getCode() == userFeedBackRO.getAnswerType()) {
                    userFeedbackVO.setCustomerImg("https://cashmama-pro.oss-ap-south-1.aliyuncs.com/banner/cs.png");
                } else {
                    userFeedbackVO.setCustomerImg("https://cashmama-pro.oss-ap-south-1.aliyuncs.com/banner/customer.png");
                }
                list.add(userFeedbackVO);
            }
            list.stream().sorted(Comparator.comparing(UserFeedbackVO::getId)).collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 保存用户困难反馈
     *
     * @param difficulties
     * @param helpContent
     */
    public void saveDifficulties(String difficulties, String helpContent) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        Response<User> userByUserCode = userService.getUserByUserCode(userCode);
        User user = userByUserCode.getData();
        Response<UserAuthEmail> userEmail = userEmailService.getUserEmail(userCode);
        UserAuthEmail email = userEmail.getData();
        UserDifficultiesFeedBackRequest userDifficultiesFeedBackRequest = new UserDifficultiesFeedBackRequest();
        userDifficultiesFeedBackRequest.setUserCode(userCode);
        userDifficultiesFeedBackRequest.setEmail(email.getEmail());
        userDifficultiesFeedBackRequest.setName(user.getName());
        userDifficultiesFeedBackRequest.setDifficulties(difficulties);
        userDifficultiesFeedBackRequest.setContent(helpContent);
        userDifficultiesFeedBackRequest.setAppCode("38");
        Response<Boolean> response = userBehaviorService.saveDifficultiesFeedback(userDifficultiesFeedBackRequest);
        if (!response.isSuccess()) {
            throw new ApplicationException(response.getCode(), response.getMsg());
        }
    }

    /**
     * 用户事件埋点
     *
     * @param userBehaviorEvent
     * @return
     */
    public boolean insertUserBehaviorEvent(UserBehaviorEventDTO userBehaviorEvent) {
        if (userBehaviorEvent == null || com.fqgj.common.utils.StringUtils.isEmpty(userBehaviorEvent.getUserCode()) || com.fqgj.common.utils.StringUtils.isEmpty(userBehaviorEvent.getEvent())) {
            return false;
        }
        UserBehaviorEventRequest userBehaviorEventRequest = new UserBehaviorEventRequest();
        BeanUtils.copyProperties(userBehaviorEvent, userBehaviorEventRequest);
        try {
            userBehaviorService.insertUserBehaviorEvent(userBehaviorEventRequest);
        } catch (Exception e) {
            LOGGER.error("=================== 埋点失败，userCode:{},e:{} =================", userBehaviorEvent.getUserCode(), e);
        }
        return true;
    }

    /**
     * 用户签到信息
     *
     * @return
     */
    public UserCheckIn signInInfo() {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        List<UserLevelRewardConfig> userLevelRewardConfigs = this.getUserLevelRewardConfig();
        UserCheckIn userCheckIn = new UserCheckIn();
        Response<List<UserLevelActionFlow>> listResponse = userLevelService.queryUserLevelActionListByOneWeek(userCode, UserRewardEnum.REWARD.getCode());
        Response<UserLevelInfo> userLevelInfo = userLevelService.getUserLevelInfo(userCode);
        if (userLevelInfo.getData() == null) {
            throw new ApplicationException(UserProfileErrorCodeEnum.USER_LEVEL_DATA_EMPTY);
        }
        this.packageWeeklyCheckList(userLevelInfo.getData(), listResponse.getData(), userLevelRewardConfigs, userCheckIn);
        return userCheckIn;
    }

    private void packageWeeklyCheckList(UserLevelInfo userLevelInfo, List<UserLevelActionFlow> userLevelActionFlows, List<UserLevelRewardConfig> userLevelRewardConfigs, UserCheckIn userCheckIn) {
        String[] weeks = new String[]{"Sun.", "Mon.", "Tue.", "Wed.", "Thur.", "Fri.", "Sat."};
        List<WeeklyCheckInVO> weeklyCheckIns = Lists.newArrayList();
        Calendar c = Calendar.getInstance();
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
        c.add(Calendar.DAY_OF_MONTH, -dayOfWeek);
        for (int i = 1; i <= 7; i++) {
            WeeklyCheckInVO weeklyCheckInVO = new WeeklyCheckInVO();
            c.add(Calendar.DAY_OF_MONTH, 1);
            if (CollectionUtils.isNotEmpty(userLevelActionFlows)) {
                for (UserLevelActionFlow userLevelActionFlow : userLevelActionFlows) {
                    if (DateUtils.isSameDay(userLevelActionFlow.getCreateDate(), c.getTime())) {
                        weeklyCheckInVO.setStatus(1);
                        weeklyCheckInVO.setRights("₹" + userLevelActionFlow.getReward());
                    }
                }
            }

            for (UserLevelRewardConfig userLevelRewardConfig : userLevelRewardConfigs) {
                if (userLevelRewardConfig.getDayOfWeek() == i) {
                    weeklyCheckInVO.setRights(userLevelRewardConfig.getType() == 1 ? ">₹1" : "₹" + userLevelRewardConfig.getReward());
                    weeklyCheckInVO.setImgType(userLevelRewardConfig.getType());
                }
                if (userLevelRewardConfig.getDayOfWeek() == dayOfWeek) {
                    userCheckIn.setImgType(userLevelRewardConfig.getType());
                }
            }
            if (dayOfWeek == i) {
                weeklyCheckInVO.setCurrentCheckIn(true);
                if (weeklyCheckInVO.getStatus() == 1) {
                    userCheckIn.setEnabledClick(false);
                    userCheckIn.setButtonText("Received Today");
                }
            }
            weeklyCheckInVO.setName(weeks[i - 1]);
            weeklyCheckInVO.setDateForWeek(c.getTime());
            weeklyCheckInVO.setDayForWeek(i);
            weeklyCheckIns.add(weeklyCheckInVO);
        }

        userCheckIn.setWeeklyCheckInList(weeklyCheckIns);
        userCheckIn.setTotalAmount(userLevelInfo == null ? "₹0" : "₹" + userLevelInfo.getTotalReward());
        userCheckIn.setBottomDescription(this.transferDescription(apolloConfigUtil.getCheckInBottomDes()));
        userCheckIn.setMiddleDescription(this.transferDescription(apolloConfigUtil.getCheckInMiddleDes()));
        userCheckIn.setScrollingTips(this.packageScrollerTips());
        LOGGER.info("============= week reward list:{} =================", JSONObject.toJSONString(weeklyCheckIns));
    }

    private CheckInDescriptionVO transferDescription(String jsonStr) {
        CheckInDescriptionVO checkInDescription = null;
        try {
            checkInDescription = JSONObject.parseObject(jsonStr, CheckInDescriptionVO.class);
        } catch (Exception e) {
            LOGGER.error("==============transfer to pojo error, e:{} ==============", e);
        }
        return checkInDescription;
    }

    private List<SchemeTipsVO> packageScrollerTips() {
        if (redisClient.get(RedisKeyConsts.USER_TIPS_SCROLLER_DDD_KEY) != null) {
            return (List<SchemeTipsVO>) redisClient.get(RedisKeyConsts.USER_TIPS_SCROLLER_DDD_KEY);
        }
        List<SchemeTipsVO> schemeTips = Lists.newArrayList();
        for (int i = 1; i <= 10; i++) {
            String mobile = SensitiveInfoUtils.mobilePhone(String.valueOf(RandomUtils.nextLong(9000000000L, 9999999999L)));
            String amount = "₹" + RandomUtils.nextInt(200, 500);
            SchemeTipsVO schemeTipsVO = new SchemeTipsVO()
                    .setTips(mobile + " sign in successfully, receive total " + amount)
                    .setHighlightText(amount);
            schemeTips.add(schemeTipsVO);
        }
        redisClient.set(RedisKeyConsts.USER_TIPS_SCROLLER_DDD_KEY, schemeTips);
        return schemeTips;
    }

    private List<UserLevelRewardConfig> getUserLevelRewardConfig() {

        if (redisClient.get(RedisKeyConsts.USER_LEVEL_CONFIG_KEY) != null) {
            return (List<UserLevelRewardConfig>) redisClient.get(RedisKeyConsts.USER_LEVEL_CONFIG_KEY);
        }
        Response<List<UserLevelRewardConfig>> userLevelRewardConfigs = userLevelService.queryUserLevelRewardConfig();
        if (CollectionUtils.isEmpty(userLevelRewardConfigs.getData())) {
            throw new ApplicationException(UserProfileErrorCodeEnum.USER_LEVEL_ERROR);
        }
        redisClient.set(RedisKeyConsts.USER_LEVEL_CONFIG_KEY, userLevelRewardConfigs.getData());
        return userLevelRewardConfigs.getData();
    }

    /**
     * 签到
     *
     * @return
     */
    public SignInResultVO signIn() {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        //并发点击
        if (!redisClient.setnx(RedisKeyConsts.USER_CHECK_IN_ONE_DAY, userCode, userCode)) {
            throw new ApplicationException(UserProfileErrorCodeEnum.USER_LEVEL_DATA_REPEAT);
        }
        Long secondsLeftToday = 86400 - DateUtils.getFragmentInSeconds(Calendar.getInstance(), Calendar.DATE);
        redisClient.expire(RedisKeyConsts.USER_CHECK_IN_ONE_DAY, secondsLeftToday.intValue(), userCode);
        Response<List<UserLevelActionFlow>> listResponse = userLevelService.queryUserLevelActionByUserCodeAndDate(userCode, UserRewardEnum.REWARD.getCode(), new Date());
        if (CollectionUtils.isNotEmpty(listResponse.getData())) {
            throw new ApplicationException(UserProfileErrorCodeEnum.USER_LEVEL_DATA_REPEAT);
        }
        List<UserLevelRewardConfig> userLevelRewardConfigs = this.getUserLevelRewardConfig();
        Calendar c = Calendar.getInstance();
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
        Integer reward = 0;
        for (UserLevelRewardConfig userLevelRewardConfig : userLevelRewardConfigs) {
            if (userLevelRewardConfig.getDayOfWeek() == dayOfWeek) {
                reward = userLevelRewardConfig.getReward();
            }
        }

        UserLevelRequest userLevelRequest = new UserLevelRequest()
                .setUserCode(userCode)
                .setType(UserRewardEnum.REWARD.getCode())
                .setScore(0)
                .setReward(reward);
        userLevelService.updateUserLevelInfo(userLevelRequest);
        LOGGER.info("============ user sign in success userCode:{}, reward:{} =============", userCode, reward);

        SignInResultVO signInResult = new SignInResultVO()
                .setTitle("Congratulations!")
                .setTips("You have received ₹" + reward)
                .setHighlightText("₹" + reward);
        return signInResult;
    }

    /**
     * 活动弹窗
     *
     * @return
     */
    public UserActivityPopupVO popup() {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        String packageName = RequestLocalInfo.getRequestBasicInfo().getPackageName();
        Response<List<UserActivity>> listResponse = userActivityService.queryActivityByUserCode(userCode, UserActivityEnum.POPUP.getCode());
        if (CollectionUtils.isEmpty(listResponse.getData())) {
            return null;
        }
        List<UserActivity> userActivities = listResponse.getData();
        UserActivityPopupVO userActivityPopup = new UserActivityPopupVO();
        userActivityPopup.setPopupId(userActivities.get(0).getActivityId());
        userActivityPopup.setImageUrl(userActivities.get(0).getImgUrl());
        userActivityPopup.setUrl(userActivities.get(0).getUrl());
        userActivityPopup.setButtonText(userActivities.get(0).getButtonText());
        return userActivityPopup;
    }

    /**
     * 已读弹窗
     *
     * @param popupId
     */
    public void readPopup(Long popupId) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        try {
            userActivityService.readActivity(popupId, userCode);
        } catch (Exception e) {
            LOGGER.error("=============== read activity error, e:{} ============", e);
        }
    }


    public UserPushRiskResult pushRisk() {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        String productCategory = RequestLocalInfo.getRequestBasicInfo().getCategoryCode();
        String appCode = appUtils.getAppCode();
        String tradeNo = System.currentTimeMillis() + Thread.currentThread().getId() + "RN" + appCode;
        UserPushRiskResult userPushRiskResult = new UserPushRiskResult();
        if (!apolloConfigUtil.permitPushToFirstRisk()) {
            LOGGER.info("== 推送到风控的开关未打开 ==");
            userPushRiskResult.setRiskNo("RISK_CLOSED");
            return userPushRiskResult;
        }
        UserAuthStatusRO userAuthStatus = this.getUserAuthStatus(userCode);
        if (userAuthStatus.getFirstRoundRiskStatus() != UserAuthStatusEnum.INIT.getCode() && userAuthStatus.getFirstRoundRiskStatus() != UserAuthStatusEnum.FAIL.getCode()) {
            Response<UserAuthFirstRiskRO> response = userAuthServiceFacade.getUserAuthFirstRiskByUserCode(userCode);
            if (response.getData() != null) {
                userPushRiskResult.setRiskNo(response.getData().getPushNo());
                LOGGER.info("============= 拦截重复推送风控，userCode:{}, status:{}, riskNo:{}, newRiskNo:{} ============", userCode, userAuthStatus.getFirstRoundRiskStatus(), userPushRiskResult.getRiskNo(), tradeNo);
                return userPushRiskResult;
            }
        }
        if (redisClient.setnx(RedisKeyConsts.USER_FIRST_PUSH_RISK_KEY, userCode, userCode)) {
            redisClient.expire(RedisKeyConsts.USER_FIRST_PUSH_RISK_KEY, TimeConsts.ONE_MINUTE, userCode);
        } else {
            userPushRiskResult.setRiskNo(tradeNo);
            LOGGER.info("================== 拦截1分钟内重复推送风控,riskNo:{}, userCode:{} ==================", tradeNo, userCode);
            return userPushRiskResult;
        }

        //推送订单
        this.push(tradeNo, userCode, productCategory);
        userPushRiskResult.setRiskNo(tradeNo);
        return userPushRiskResult;
    }

    public void push(String tradeNo, String userCode, String productCategory) {

        Integer firstEmergencyMaxOverdueDays = 0;
        Integer secondEmergencyMaxOverdueDays = 0;
        UserSocialContact userSocialContact = userContactService.getUserSocialContactByUserCode(userCode).getData();
        if (Objects.nonNull(userSocialContact)) {
            UserEmergencyContact userEmergencyContact = userSocialContact.getUserEmergencyContact();
            if (Objects.nonNull(userEmergencyContact)) {
                UserFamilyContact userFamilyContact = userEmergencyContact.getUserFamilyContact();
                if (Objects.nonNull(userFamilyContact)) {
                    //第一紧急联系人的最大逾期情况
                    UserAccessInfo firstAuth = userService.getUserAccessInfoByMobile(userFamilyContact.getMobile(), "5").getData();
                    if (Objects.nonNull(firstAuth)) {
                        firstEmergencyMaxOverdueDays = orderService.getMaxOverDueDays(firstAuth.getUserCode());
                    }
                }
                UserFriendContact userFriendContact = userEmergencyContact.getUserFriendContact();
                if (Objects.nonNull(userFriendContact)) {
                    //第二紧急联系人的最大逾期情况
                    UserAccessInfo secondAuth = userService.getUserAccessInfoByMobile(userFamilyContact.getMobile(), "5").getData();
                    if (Objects.nonNull(secondAuth)) {
                        secondEmergencyMaxOverdueDays = orderService.getMaxOverDueDays(secondAuth.getUserCode());
                    }
                }
            }
        }

        UserPushRiskRequest userPushRiskRequest = new UserPushRiskRequest();
        userPushRiskRequest.setPushNo(tradeNo);
        userPushRiskRequest.setAppCode(PackageNameEnum.getLowercaseAppName(RequestLocalInfo.getRequestBasicInfo().getPackageName()));
        userPushRiskRequest.setUserCode(userCode);
        userPushRiskRequest.setBiz(5);
        userPushRiskRequest.setProductCategory(productCategory);
        userPushRiskRequest.setFirstEmergencyMaxOverdueDays(firstEmergencyMaxOverdueDays);
        userPushRiskRequest.setSecondEmergencyMaxOverdueDays(secondEmergencyMaxOverdueDays);
        userPushRiskRequest.setCallBackUrl(apolloConfigUtil.getApiWebPath() + "/risk/v1/callback");
        this.packageBillParam(userCode, userPushRiskRequest);
        Response<Boolean> response = userAuthServiceFacade.pushFirstRoundRisk(userPushRiskRequest);
        if (!response.isSuccess()) {
            throw new ApplicationException(response.getMsg());
        }

        LOGGER.info("================== 最终推送风控成功,riskNo:{}, userCode:{} ==================", tradeNo, userCode);
    }

    private void packageBillParam(String userCode, UserPushRiskRequest userPushRiskRequest) {

        List<BillVO> billVOs = Lists.newArrayList();
        Response<UserPanInfo> userPanInfoResponse = userPanService.getByUserCode(userCode);
        if (userPanInfoResponse.getData() != null) {
            String panCardNo = StringUtils.isBlank(userPanInfoResponse.getData().getCardNo()) ? userPanInfoResponse.getData().getManualCardNo() : userPanInfoResponse.getData().getCardNo();
            Response<List<UserPanInfo>> listByPanNo = userPanService.getListByPanNo(panCardNo);
            if (listByPanNo != null && CollectionUtils.isNotEmpty(listByPanNo.getData())) {
                List<UserPanInfo> userPanInfos = listByPanNo.getData();
                List<String> userCodes = userPanInfos.parallelStream().map(UserPanInfo::getUserCode).collect(Collectors.toList());
                List<BillVO> billVOsTmp = billQueryService.queryByUserCodes(userCodes).getData();
                if (CollectionUtils.isNotEmpty(billVOsTmp)) {
                    billVOs.addAll(billVOsTmp);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(billVOs)) {
            billVOs = billVOs.stream().sorted((e1, e2) -> e2.getRepaymentDate().compareTo(e1.getRepaymentDate())).collect(Collectors.toList());
            this.packageRiskRequest(billVOs, userPushRiskRequest);
        }
    }

    private void packageRiskRequest(List<BillVO> billVOS, UserPushRiskRequest userPushRiskRequest) {
        int loanTotalNum = 0;
        int overdueNum = 0;
        int obeyNum = 0;
        int maxOverdueDays = 0;
        int overDueTotalDays = 0;
        int lastOverdueDays = 0;
        int activeOrdersNum = 0;
        int notTimedOrdersNum = 0;
        double advancePayOffTotalDays = 0.0;

        if (CollectionUtils.isNotEmpty(billVOS)) {
            loanTotalNum = billVOS.size();
            for (BillVO billVO : billVOS) {
                if (billVO.getOverdueDays() > 0) {
                    overdueNum++;
                }
                if (billVO.getPayOffDate() != null) {
                    obeyNum++;
                }
                Date repaymentDate = TimeUtils.getDate("yyyy-MM-dd", billVO.getRepaymentDate());
                boolean isTimed = TimeUtils.diffDays(repaymentDate, new Date()) > 0;
                if (!isTimed) {
                    notTimedOrdersNum++;
                }
                if (billVO.getOverdueDays() > maxOverdueDays) {
                    maxOverdueDays = billVO.getOverdueDays();
                }
                overDueTotalDays += billVO.getOverdueDays();
                // 所有未还的订单
                if (BillPaidStatusEnum.CLEAR_REPAYMENT.getStatus() != billVO.getPaidStatus().getStatus()) {
                    activeOrdersNum++;
                }
                lastOverdueDays = billVO.getOverdueDays();
            }
        }
        //计算平均逾期天数和平均提前还款天数
        double aveOverdueDays = 0.0;
        double aveAdvancePayOffDays = 0.0;
        if (overdueNum > 0) {
            aveOverdueDays = overDueTotalDays / overdueNum;
        }
        if (obeyNum > 0) {
            aveAdvancePayOffDays = advancePayOffTotalDays / obeyNum;
        }
        userPushRiskRequest.setLoanTotalNum(loanTotalNum);
        userPushRiskRequest.setObeyNum(obeyNum);
        userPushRiskRequest.setActiveOrdersNum(activeOrdersNum);
        userPushRiskRequest.setOverdueNum(overdueNum);
        userPushRiskRequest.setMaxOverdueDays(maxOverdueDays);
        userPushRiskRequest.setLastOverdueDays(lastOverdueDays);
        userPushRiskRequest.setAveAdvancePayOffDays(aveAdvancePayOffDays);
        userPushRiskRequest.setAveOverdueDays(aveOverdueDays);
    }

    /**
     * 查询第一轮风控结果
     *
     * @param riskNo
     * @return
     */
    public UserQueryRiskResult riskResult(String riskNo) {

        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        String mobile = RequestLocalInfo.getCurrentUser().getMobile();
        String appCode = RequestLocalInfo.getRequestBasicInfo().getAppCode();
        String packageName = RequestLocalInfo.getRequestBasicInfo().getPackageName();
        UserQueryRiskResult userQueryRiskResult = new UserQueryRiskResult();
        userQueryRiskResult.setJumperUrl(JumpRouterEnum.HOME.getJumpUrl());

        UserPushRiskCallbackRequest userPushRiskRequest = new UserPushRiskCallbackRequest();
        userPushRiskRequest.setPushNo(riskNo);
        userPushRiskRequest.setRiskResult(apolloConfigUtil.manualRiskResult());
        if ("pass".equalsIgnoreCase(apolloConfigUtil.manualRiskResult())) {
            boolean isCreditComplete = apiUserCenterService.isCreditComplete(userCode);
            if (!isCreditComplete) {
                apiUserCenterService.initializationQuota(userCode);
            }
            userPushRiskRequest.setRiskStatus(UserAuthStatusEnum.SUCCESS.getCode());
            userAuthServiceFacade.firstRoundRiskCallBack(userPushRiskRequest);
            userQueryRiskResult.setStatus(1);
            return userQueryRiskResult;
        } else if ("reject".equalsIgnoreCase(apolloConfigUtil.manualRiskResult())) {
            userPushRiskRequest.setRiskStatus(UserAuthStatusEnum.REJECT.getCode());
            userAuthServiceFacade.firstRoundRiskCallBack(userPushRiskRequest);
            userQueryRiskResult.setStatus(5);
            return userQueryRiskResult;
        }
        Response<UserAuthFirstRiskRO> userAuthFirstRisk = userAuthServiceFacade.getUserAuthFirstRisk(riskNo);
        UserAuthFirstRiskRO userAuthFirstRiskResult = userAuthFirstRisk.getData();
        if (userAuthFirstRiskResult != null) {
            switch (userAuthFirstRiskResult.getRiskStatus()) {
                case 4://处理中
                    userQueryRiskResult.setStatus(0);
                    break;
                case 1://通过
                    userQueryRiskResult.setStatus(1);
                    break;
                case 2://失败
                    userQueryRiskResult.setStatus(2);
                    break;
                case 5://拒绝
                    userQueryRiskResult.setStatus(5);
                    break;
                default:
                    break;
            }
            boolean isCreditComplete = apiUserCenterService.isCreditComplete(userCode);
            if (!isCreditComplete) {
                apiUserCenterService.initializationQuota(userCode);
            }
        }
        if (apolloConfigUtil.auditMobiles().contains(mobile) && userAuthFirstRiskResult.getRiskStatus() == 4) {
            UserPushRiskCallbackRequest userPushRiskCallbackRequest = new UserPushRiskCallbackRequest()
                    .setPushNo(userAuthFirstRiskResult.getPushNo())
                    .setRiskResult("audit mobile mock success")
                    .setRiskStatus(1);
            Response<Boolean> response = userAuthServiceFacade.firstRoundRiskCallBack(userPushRiskCallbackRequest);
            if (!response.isSuccess()) {
                throw new ApplicationException(response.getCode(), response.getMsg());
            }
        }
        return userQueryRiskResult;
    }

    public void infoSubmit(JSONObject jsonObject) {
        if (jsonObject != null) {
            String result = jsonObject.toJSONString();
            LOGGER.info("==== advance result 结果上报:{} ====", result);
            if (!result.contains("SUCCESS")) {
                redisClient.del(RedisKeyConsts.ADVANCE_LICENCE_KEY);
            }
        }
    }


    public void addPromotion(UserPromotionVo promotionVo) {
        UserPromotion userPromotion = new UserPromotion();
        userPromotion.setActionType(promotionVo.getActionType());
        userPromotion.setActionAccess(promotionVo.getActionAccess());
        userPromotion.setActionDate(new Date());
        userInfoService.addUserPromotion(userPromotion);
    }

    public void initPromotion(String userCode) {
        UserPromotion userPromotion = new UserPromotion();
        userPromotion.setUserCode(userCode);
        userPromotion.setActionAccess(1);
        userPromotion.setActionType(0);
        userPromotion.setActionDate(new Date());
        userInfoService.addUserPromotion(userPromotion);
    }
}
